#pragma once
#include <iostream>
#include <sstream>
#include <string>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

// 使用宏进行一个代理
#define LOG(level, format, ...) log(__FILE__, __LINE__, level, format, ##__VA_ARGS__)

enum Level
{
    DEBUG,
    INFO,
    WARN,
    ERROR,
    FAITAL
};
std::string LocalTime()
{
    time_t t = time(nullptr);
    struct tm *ptm = localtime(&t);
    std::stringstream ss;
    ss << "[" << std::to_string(ptm->tm_year + 1900) << "-";
    ss << std::to_string(ptm->tm_mon + 1) << "-";
    ss << std::to_string(ptm->tm_mday) << " ";
    ss << std::to_string(ptm->tm_hour) << ":";
    ss << std::to_string(ptm->tm_min) << ":";
    ss << std::to_string(ptm->tm_sec) << "]";
    return ss.str();
}

std::string to_str(Level level)
{
    switch (level)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARN:
        return "WARN";
    case ERROR:
        return "ERROR";
    case FAITAL:
        return "FAITAL";
    default:
        return "UNKNOW";
    }
}
// [level] [2024/3/18 23:48] [file:line] info\n
void log(const char *file, int line, Level level, const char *format, ...)
{
    va_list vl;
    va_start(vl, format);
    std::string time = LocalTime();
    char info[64];
    vsnprintf(info, sizeof(info), format, vl);
    std::stringstream loginfo;
    loginfo << "[" << to_str(level) << "] ";
    loginfo << time << " [" << file << ":" << std::to_string(line) << "] ";
    loginfo << info << '\n';
    // std::cout << loginfo.str();
    // 当进程是守护进程后，不能输出到终端上，需要重定向到文件中

    int fd = open("./Log.txt", O_CREAT | O_APPEND | O_RDWR, 0666);
    if(fd < 0)
    {
        std::cout << "fd = " << fd << std::endl;
        printf("LOG::failed %d-%s\n",errno,strerror(errno));
        exit(-1);
    }
    dup2(fd,1);
    printf("%s",loginfo.str().c_str());
    close(fd);
}